{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# QCoDeS Example with Keysight 34980A Multifunction Switch / Measure Mainframe and Modules" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Instrument Short info\n", "The 34980A Multifunction Switch / Measure Unit is a compact, economical, one-box solution for medium to high-density switch/measure applications. It requires different types of modules, such as Matrix Modules, Multiplexer Modules, and RF & Microwave Modules, for different applications. In this example notebook, I'll forcus on the Matrix Modules.\n", "\n", "There are four different Matrix Modules, 34931A, 34932A, 34933A, and 34934A. Each can be configured into different layout, such as 4x8, 8x32 matrix. In this example notebook, two 34934A modules are connected to slot 1 and slot 2 of the 34980A system.\n", "\n", "Each 34934A module is configured into a 8x64 matrix (8 rows, 64 columns), and connected with each other by rows. As a result, they form a 8x128 matrix (8 rows, 128 columns)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from IPython.display import Markdown, display\n", "from pyvisa.errors import VisaIOError\n", "\n", "from qcodes.instrument_drivers.Keysight import Keysight34980A" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[swmx(Keysight34980A)] Could not connect at TCPIP0::1.1.1.1::inst0::INSTR\n", "Traceback (most recent call last):\n", " File \"C:\\Users\\jenielse\\source\\repos\\Qcodes\\qcodes\\instrument\\visa.py\", line 116, in _connect_and_handle_error\n", " visa_handle, visabackend = self._open_resource(address, visalib)\n", " File \"C:\\Users\\jenielse\\source\\repos\\Qcodes\\qcodes\\instrument\\visa.py\", line 139, in _open_resource\n", " resource_manager = pyvisa.ResourceManager()\n", " File \"C:\\Users\\jenielse\\Miniconda3\\envs\\qcodespip310\\lib\\site-packages\\pyvisa\\highlevel.py\", line 2992, in __new__\n", " visa_library = open_visa_library(visa_library)\n", " File \"C:\\Users\\jenielse\\Miniconda3\\envs\\qcodespip310\\lib\\site-packages\\pyvisa\\highlevel.py\", line 2899, in open_visa_library\n", " wrapper = _get_default_wrapper()\n", " File \"C:\\Users\\jenielse\\Miniconda3\\envs\\qcodespip310\\lib\\site-packages\\pyvisa\\highlevel.py\", line 2858, in _get_default_wrapper\n", " raise ValueError(\n", "ValueError: Could not locate a VISA implementation. Install either the IVI binary or pyvisa-py.\n", "WARNING:root:For slot 3, no configuration moduleconnected, or safety interlock jumper removed. Making any connection is not allowed\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Connected to: Keysight 34980A (serial:1000, firmware:0.1) in 0.06s\n" ] }, { "data": { "text/markdown": [ "**Note: using simulated instrument.**\n", "\n", "Due to limitations in pyvisa-sim the behavior will be different. See the keysight_34980A.yaml file for more detial." ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# instantiate the Swith Matrix\n", "try:\n", " switch_matrix = Keysight34980A(\"swmx\", \"TCPIP0::1.1.1.1::inst0::INSTR\")\n", " print('using physical instrument')\n", "except (ValueError, VisaIOError):\n", " # Below is an example how to set up the mock instrument\n", "\n", " switch_matrix = Keysight34980A('switch_matrix_sim',\n", " address='GPIB::1::INSTR',\n", " pyvisa_sim_file=\"keysight_34980A.yaml\")\n", " display(Markdown(\"\"\"**Note: using simulated instrument.**\n", "\n", "Due to limitations in pyvisa-sim the behavior will be different. See the keysight_34980A.yaml file for more detial.\"\"\"))" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{1: {'vendor': 'Agilent Technologies',\n", " 'model': '34934A-8x64',\n", " 'serial': 'MY56480560',\n", " 'firmware': '1.01'},\n", " 2: {'vendor': 'Agilent Technologies',\n", " 'model': '34934A-8x64',\n", " 'serial': 'MY56480559',\n", " 'firmware': '1.01'}}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# show the module information for each occupied slot\n", "switch_matrix.system_slots_info" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each module is defined as an instance of the submodule class. To access the module in slot n, use the following:\n", "\n", "**switch_matrix.module[n]**\n", "\n", "where **n** is the **slot** number" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# to access the module installed in slot 1:\n", "switch_matrix.module[1]" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# to access the module installed in slot 2:\n", "switch_matrix.module[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to access each module via the following:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# to access the module installed in slot 1:\n", "switch_matrix.slot_1_34934A" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# to access the module installed in slot 1:\n", "switch_matrix.slot_2_34934A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Switch control, module level" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For each module, any of the 8 row can be connected to any of the 64 column." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "switch_matrix.module[1].connect(2, 34) # connect row 2 to column 34, , for module in slot 1\n", "print(switch_matrix.module[1].is_closed(2, 34)) # check if row 2 is connected to column 34" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "switch_matrix.slot_1_34934A.disconnect(2, 34) # disconnect row 2 from column 34, for module in slot 1\n", "print(switch_matrix.module[1].is_open(2, 34)) # check if row 2 is disconnect from column 34" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "switch_matrix.module[2].connect(3, 45) # connect row 3 to column 45, , for module in slot 2\n", "print(switch_matrix.module[2].is_closed(3, 45)) # check if row 3 is connected to column 45" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We expect the following command to raise an exception because the column value 67 is out of range for module in slot 1." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "row/column value out of range\n" ] } ], "source": [ "try:\n", " switch_matrix.module[1].connect(5, 67)\n", "except ValueError as err:\n", " print(err)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because the two 8x64 matrices are connected by row to form a 8x128 matrix, user should convert column 67 to the correct column in the second module: 67-64=3, then use the connect function of module in slot 2:\n", "\n", "**switch_matrix.module_in_slot[2].connect_path(5, 3)**" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "switch_matrix.module[2].connect(5, 3)\n", "print(switch_matrix.module[2].is_closed(5, 3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To connect multiple channels: (again, the channels should belong to the one module)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[True, True, True]\n" ] } ], "source": [ "connections = [(3, 14), (1, 59), (2, 6)]\n", "switch_matrix.module[2].connect_paths(connections)\n", "print(switch_matrix.module[2].are_closed(connections))" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[True, True, True]\n" ] } ], "source": [ "switch_matrix.module[2].disconnect_paths(connections)\n", "print(switch_matrix.module[2].are_open(connections))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## About safety interlock" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Safety Interlock feature prevents connections to the Analog Buses if no terminal block or properly-wired cable is connected to the module. When a module is in safety interlock state, all the channels are disconnected/open, user can not connect/close any channels.\n", "\n", "In the event of safety interlock, there will be a warning message. In the following example I manually changed the flag, **DO NOT** do this in the real situation." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "switch_matrix.module[2]._is_locked = True # DO NOT perform this action in real situation" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:Warning: no configuration module connected, or safety interlock enabled. Making any connection is not allowed\n" ] } ], "source": [ "switch_matrix.module[2].connect(1,2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Actions which make not atempt to connect any channels are still work:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "switch_matrix.module[2].is_open(3,4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### For module 34934A only\n", "There is a relay protection mode for 34934A module. The fastest switching speeds for relays in a given signal path are achieved using the FIXed or ISOlated modes, followed by the AUTO100 and AUTO0 modes. There may be a maximum of 200 Ohm of resistance, which can only be bypassed by \"AUTO0\" mode.\n", "See user's guide and programmer's reference for detailed explanation." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'AUTO100'" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# to see the current protection mode of the module in slot 1:\n", "switch_matrix.module[1].protection_mode()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'AUTO0'" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# to set the protection mode to 'AUTO0', for module in slot 1:\n", "switch_matrix.module[1].protection_mode('AUTO0')\n", "switch_matrix.module[1].protection_mode()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Switch control, instrument level" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can disconnect all the channels in a certain module, or all the installed modules" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "# to disconnect the channels in module installed in slot 1\n", "switch_matrix.disconnect_all(1)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "# to disconnect the channels in all installed modules\n", "switch_matrix.disconnect_all()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## So, when to use connect, connect_paths, is_closed, or are_closed?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Yes, it seem very confusing because of the path/paths, and is/are.\n", "\n", "The reason for the singular/plural is that the module can work with one row and column pair (r, c), or a list of row and column pairs [(r1, c1), (r2, c2)].\n", "\n", "**When work with single row-column pair, use the singular version of functions**\n", " - instrument.module.connect(r, c)\n", " - instrument.module.is_closed(r,c)\n", " \n", "**When work with list of row-column pairs, use the plural version of functions**\n", " - instrument.module.connect_paths([(r1, c1), (r2, c2)])\n", " - instrument.module.are_closed([(r1, c1), (r2, c2)])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6" }, "nbsphinx": { "execute": "never" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }